package iterators;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import config.GlobalConfig;
import controlFlowGraph.CFG;
import controlFlowGraph.CFGEdge;
import controlFlowGraph.CFGNode;
import domains.AnalysisDomain;

public class Worklist extends FixpointIterator {

	@Override
	public void doIteration(CFG cfg) {
		HashMap<CFGNode,Set<CFGNode>> dependencies = new HashMap<CFGNode,Set<CFGNode>>();
		for(CFGNode c : cfg.getAllNodes()){
			dependencies.put(c,computeDependencies(c,cfg));
		}
		
		Set<CFGNode> worklist = new HashSet<CFGNode>();
		worklist.addAll(cfg.getAllNodes());
		while(!worklist.isEmpty()){
			CFGNode next = worklist.iterator().next();
			worklist.remove(next);
			if (GlobalConfig.debug) {
				System.out.println("Processing node: "+ next.getId());
			}
			AnalysisDomain newVal = recompute(next);
			if(!newVal.equals(next.getAnalysisInfo())){
				next.setAnalysisInfo(newVal);
				worklist.addAll(dependencies.get(next));
			}
		}
		
	}

	private Set<CFGNode> computeDependencies(CFGNode node, CFG cfg){
		Set<CFGNode> dependent = new HashSet<CFGNode>();
		if(GlobalConfig.isForward()){
			List<CFGEdge> out = node.getOutEdges();
			for(CFGEdge e: out){
				dependent.add(e.getToNode());
			}
		} else if(GlobalConfig.isBackward()){
			List<CFGEdge> in = node.getInEdges();
			for(CFGEdge e: in){
				dependent.add(e.getFromNode());
			}
		} else {
			System.out.println("Analysis Type not supported!");
		}
		return dependent;
	}
}
